package cn.demo.day7;

import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class TetrisGame extends JPanel {

    // 正在下落的方块
    private Tetromino currentOne = Tetromino.randomOne();
    // 即将下落的方块
    private Tetromino nextOne = Tetromino.randomOne();
    // 墙 20行10列的方格
    private Cell[][] wall = new Cell[20][10];
    private static final int CELL_SIZE = 26;
    // 统计分数
    int[] scores_pool = {0, 1, 3, 5, 10};
    private int totalScore = 0;
    private int totalLine = 0;

    public static BufferedImage T = null;
    public static BufferedImage S = null;
    public static BufferedImage O = null;
    public static BufferedImage Z = null;
    public static BufferedImage I = null;
    public static BufferedImage J = null;
    public static BufferedImage L = null;
    public static BufferedImage background = null;

    public static void initImage() {
        try {
            /*
             * 加载图片
             */
            T = ImageIO.read(TetrisGame.class.getResource("T.png"));
            S = ImageIO.read(TetrisGame.class.getResource("S.png"));
            O = ImageIO.read(TetrisGame.class.getResource("O.png"));
            Z = ImageIO.read(TetrisGame.class.getResource("Z.png"));
            I = ImageIO.read(TetrisGame.class.getResource("I.png"));
            J = ImageIO.read(TetrisGame.class.getResource("J.png"));
            L = ImageIO.read(TetrisGame.class.getResource("L.png"));
            background = ImageIO.read(TetrisGame.class.getResource("tetris.png"));
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    public static void main(String[] args) {

        // 创建窗口
        JFrame frame = new JFrame("俄罗斯方块");
        initImage();
        // 设置窗口的可见性
        frame.setVisible(true);
        // 设置窗口的大小
        frame.setSize(535, 580);
        frame.setLocationRelativeTo(null);// 窗口居中
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 窗口关闭即程序结束
        // 创建游戏界面，即面板
        TetrisGame panel = new TetrisGame();
        frame.add(panel);

        panel.start();
    }

    /*
     * 重写JPanel中的paint()方法
     */
    @Override
    public void paint(Graphics g) {
        // 绘制背景(图片，横坐标，纵坐标，observer)
        /*
         * g.drawImage(image,x,y,null)
         * x,y为开始绘制时的坐标
         */

        // 平移坐标轴
        g.translate(15, 15);
        // 绘制墙
        paintWall(g);
        // 绘制正在下落的4格方块
        paintCurrentOne(g);
        // 绘制下一个将要绘制的4格方块
        paintNextOne(g);
        // g.drawImage(background, 0, 0, null);
    }

    /*
     * 绘制下一个将要下落的四个方块，
     * 绘制到面板的右上角的相应位置
     */
    public void paintNextOne(Graphics g) {
        Cell cells[] = nextOne.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            int x = col * CELL_SIZE + 260;
            int y = row * CELL_SIZE + 26;
            g.drawImage(cell.getImage(), x, y, null);
        }
    }

    /*
     * 绘制墙
     */
    public void paintWall(Graphics g) {
        for (int i = 0; i < 20; i++) {
            for (int j = 0; j < 10; j++) {
                int x = CELL_SIZE * j;
                int y = CELL_SIZE * i;
                Cell cell = wall[i][j];
                if (cell == null) {
                    g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
                } else {
                    g.drawImage(cell.getImage(), x, y, null);
                }
            }
        }
    }

    /*
     * 绘制正在落下的方块
     *
     */
    public void paintCurrentOne(Graphics g) {
        Cell cells[] = currentOne.cells;
        for (Cell cell : cells) {
            int x = cell.getCol() * CELL_SIZE;
            int y = cell.getRow() * CELL_SIZE;
            g.drawImage(cell.getImage(), x, y, null);
        }
    }

    public void start() {
        KeyListener keyListener = new KeyListener() {
            @Override
            public void keyPressed(KeyEvent arg0) {
                // TODO Auto-generated method stub
                int code = arg0.getKeyCode();
                switch (code) {
                    case KeyEvent.VK_LEFT:
                        moveLeftAction();
                        break;
                    case KeyEvent.VK_RIGHT:
                        moveRightAction();
                    case KeyEvent.VK_DOWN:
                        softDropAction();
                }
                repaint();
            }

            @Override
            public void keyReleased(KeyEvent e) {
            }

            @Override
            public void keyTyped(KeyEvent e) {
            }
        };

        this.addKeyListener(keyListener);
        this.requestFocus();

        while (true) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

            if (canDrop()) {
                currentOne.softDrop();
            } else {
                landToWall();
                currentOne = nextOne;
                nextOne = Tetromino.randomOne();
            }
            repaint();
        }
    }

    protected void moveLeftAction() {
        currentOne.moveLeft();
        if (outOfBounds() || coincide()) {
            currentOne.moveRight();
        }
    }

    protected void moveRightAction() {
        currentOne.moveRight();
        if (outOfBounds() || coincide()) {
            currentOne.moveLeft();
        }
    }

    protected void softDropAction() {
        if (canDrop()) {
            currentOne.softDrop();
        } else {
            landToWall();
            currentOne = nextOne;
            nextOne = Tetromino.randomOne();
        }
    }

    /*
     * 是否越界
     */
    public boolean outOfBounds() {
        Cell[] cells = currentOne.cells;
        for (Cell cell : cells) {
            if (cell.getCol() < 0 || cell.getCol() > 9 || cell.getRow() > 19 || cell.getRow() < 0) {
                return true;
            }
        }
        return false;
    }

    /*
     * 重合
     */
    public boolean coincide() {
        Cell[] cells = currentOne.cells;
        for (Cell cell : cells) {
            if (wall[cell.getRow()][cell.getCol()] != null) {
                return true;
            }
        }
        return false;
    }

    /*
     * 是否可以下落
     */
    public boolean canDrop() {
        Cell cells[] = currentOne.cells;
        for (Cell cell : cells) {
            /*
             * 获取每个元素的行号和列号
             * 判断只要有一个元素的下一行上有方块
             * 或者只要有一个元素到达最后一行
             * 便不能下落
             */
            if (cell.getRow() == 19) {
                return false;
            }
            if (wall[cell.getRow()][cell.getCol()] != null) {
                return false;
            }
        }
        return true;
    }

    /*
     * 当方块不能下落时，需要将四方块嵌入到墙中
     * 储存到二维数组中的相应位置
     */
    public void landToWall() {
        Cell[] cells = currentOne.cells;
        for (Cell cell : cells) {
            wall[cell.getRow()][cell.getCol()] = cell;
        }
    }

    /*
     * 快速下落
     */
    public void handDropAction() {
        while (true) {
            if (canDrop()) {
                currentOne.softDrop();
            } else {
                break;
            }
        }
        landToWall();
        destroyLine();// 消行
        currentOne = nextOne;
        nextOne = Tetromino.randomOne();
    }

    /*
     * 消行
     */
    public void destroyLine() {
        // 取出已经嵌入墙内的行号和列号
        Cell[] cells = currentOne.cells;
        int lines = 0;
        for (Cell cell : cells) {
            int row = cell.getRow();
            while (row < 20) {
                if (isFullLine(row)) {
                    wall[row] = new Cell[10];
                    for (int i = row; i > 0; i--) {
                        System.arraycopy(wall[i - 1], 0, wall[i], 0, 10);
                    }
                    wall[0] = new Cell[10];
                    lines++;
                }
                row++;
            }
        }
        totalScore += scores_pool[lines];
        totalLine += lines;
    }

    /*
     * 判断是否满行
     */
    public boolean isFullLine(int row) {
        Cell[] line = wall[row];
        for (Cell cell : line) {
            if (cell == null) {
                return false;
            }
        }
        return true;
    }

    /*
     * 判断游戏暂停与结束
     */
    public boolean isGameOver() {
        Cell[] cells = nextOne.cells;
        for (Cell cell : cells) {
            if (wall[cell.getRow()][cell.getCol()] != null) {
                return true;
            }
        }
        return false;
    }

}
